using System;
using System.Collections.Generic;
using System.Text;

namespace MIS.EN.Exchange.Entities
{
    /// <summary>
    /// Represents all of the Microsoft Exchange properties for items that are appointments.
    /// </summary>
    public class Appointment : Item
    {
        #region Constructors

        /// <summary>
        /// Default public constructor.
        /// </summary>
        public Appointment() 
            : this(false)
        {
        }

        /// <summary>
        /// Internal constructor used to let the base class know the item is being loaded from the server.
        /// </summary>
        /// <param name="loadedFromServer">True indicates that the item is being loaded from the server.</param>
        internal Appointment(bool loadedFromServer)
            : base(loadedFromServer)
        {
        }

        /// <summary>
        /// Overloaded public constructor.
        /// </summary>
        /// <param name="location"></param>
        /// <param name="startDate"></param>
        /// <param name="endDate"></param>
        /// <param name="instanceType"></param>
        /// <param name="attendeeStatus"></param>
        /// <param name="meetingStatus"></param>
        /// <param name="allDayEvent"></param>
        /// <param name="responseRequested"></param>
        /// <param name="reminderOffset"></param>
        /// <param name="subject"></param>
        /// <param name="textDescription"></param>
        /// <param name="timeZoneId"></param>
        public Appointment(string location, DateTime startDate, DateTime endDate, InstanceType? instanceType,
            BusyStatus attendeeStatus, MeetingStatus meetingStatus, bool allDayEvent, bool responseRequested,
            int reminderOffset, string subject, string textDescription, TimeZoneId timeZoneId)
        {
            this.location = location;
            this.startDate = startDate;
            this.endDate = endDate;
            this.instanceType = instanceType;
            this.BusyStatus = attendeeStatus;
            this.meetingStatus = meetingStatus;
            this.allDayEvent = allDayEvent;
            this.responseRequested = responseRequested;
            this.reminderOffset = reminderOffset;
            this.subject = subject;
            this.textDescription = textDescription;
            this.timeZoneId = timeZoneId;
        }

        #endregion

        #region Properties

        private DateTime startDate;

        /// <summary>
        /// Specifies the date and time when an appointment or meeting starts.  Maps to the dtstart field.
        /// </summary>
        public DateTime StartDate
        {
            get { return this.startDate; }
            set { this.startDate = value; }
        }
        private DateTime endDate;

        /// <summary>
        /// Specifies the date and time when an appointment or meeting ends.  Maps to the dtend field.
        /// </summary>
        public DateTime EndDate
        {
            get { return this.endDate; }
            set { this.endDate = value; }
        }

        private InstanceType? instanceType;

        /// <summary>
        /// Specifies the type of an appointment.  Maps to the instancetype field.
        /// </summary>
        public InstanceType? InstanceType
        {
            get { return this.instanceType; }
            set { this.instanceType = value; }
        }
        private BusyStatus busyStatus = BusyStatus.Free;

        /// <summary>
        /// Specifies whether the attendee is busy at the time of an appointment on their calendar.  Maps to the busystatus field.
        /// </summary>
        public BusyStatus BusyStatus
        {
            get { return this.busyStatus; }
            set { this.busyStatus = value; }
        }

        private MeetingStatus meetingStatus = MeetingStatus.Confirmed;
        
        /// <summary>
        /// Specifies the status of an appointment or meeting.  Maps to the meetingstatus field.
        /// </summary>
        public MeetingStatus MeetingStatus
        {
            get { return this.meetingStatus; }
            set { this.meetingStatus = value; }
        }

        private bool allDayEvent;

        /// <summary>
        /// Specifies whether the appointment or meeting is scheduled for an entire day. 
        /// Setting this property does not affect the start time or the end time of the 
        /// appointment or meeting.  Maps to the alldayevent field.
        /// </summary>
        public bool AllDayEvent
        {
            get { return this.allDayEvent; }
            set { this.allDayEvent = value; }
        }

        private bool responseRequested;

        /// <summary>
        /// Indicates if the originator of the meeting requested a response. Returns true if 
        /// a response is requested.  Maps to the responserequested field.
        /// </summary>
        public bool ResponseRequested
        {
            get { return this.responseRequested; }
            set { this.responseRequested = value; }
        }

        private int? reminderOffset;

        /// <summary>
        /// Specifies the number of seconds before an appointment starts that a reminder is 
        /// to be displayed.  Maps to the reminderoffset field.
        /// </summary>
        public int? ReminderOffset
        {
            get { return this.reminderOffset; }
            set { this.reminderOffset = value; }
        }
        
        private TimeZoneId? timeZoneId;

        /// <summary>
        /// Specifies the time zone identifier of an appointment or meeting.  Maps to the 
        /// timezoneid field.
        /// </summary>
        public TimeZoneId? TimeZoneId
        {
            get { return this.timeZoneId; }
            set { this.timeZoneId = value; }
        }

        /// <summary>
        /// The name of the item as it is saved in the Exchange store.  This is mapped to the Subject property.
        /// </summary>
        public override string Name
        {
            get { return this.subject; }
        }

        private string billingInformation = string.Empty;

        /// <summary>
        /// The billing information for a contact. Maps to the billinginformation field.
        /// </summary>
        public string BillingInformation
        {
            get { return this.billingInformation; }
            set
            {
                this.billingInformation = value;
                this.AddPropertyChanged("BillingInformation");
            }
        }

        private string companies = string.Empty;

        /// <summary>
        /// A multivalued property used by Microsoft Outlook to list one or more companies associated 
        /// with Exchange store content.  Maps to the companies field.
        /// </summary>
        public string Companies
        {
            get { return this.companies; }
            set
            {
                this.companies = value;
                this.AddPropertyChanged("Companies");
            }
        }

        private string contact = string.Empty;

        /// <summary>
        /// Specifies the name of a contact who is an attendee of a meeting.  Maps to the contact field.
        /// </summary>
        public string Contact
        {
            get { return this.contact; }
            set
            {
                this.contact = value;
                this.AddPropertyChanged("Contact");
            }
        }

        private string contactUrl = string.Empty;

        /// <summary>
        /// Specifies a URL where you can access contact information in HTML format.  Maps to the contacturl field.
        /// </summary>
        public string ContactUrl
        {
            get { return this.contactUrl; }
            set
            {
                this.contactUrl = value;
                this.AddPropertyChanged("ContactUrl");
            }
        }

        private DateTime? created;

        /// <summary>
        /// Specifies the date and time that the organizer created 
        /// the appointment or meeting. The value of this field is the same in the 
        /// original appointment and in the copy that is sent to each attendee.  
        /// Maps to the created field.
        /// </summary>
        public DateTime? Created
        {
            get { return this.created; }
            set
            {
                this.created = value;
                this.AddPropertyChanged("Created");
            }
        }

        private string descriptionUrl = string.Empty;

        /// <summary>
        /// Specifies the URL of a resource that contains a description of an appointment 
        /// or meeting.  Maps to the descriptionurl field.
        /// </summary>
        public string DescriptionUrl
        {
            get { return this.descriptionUrl; }
            set
            {
                this.descriptionUrl = value;
                this.AddPropertyChanged("DescriptionUrl");
            }
        }

        private DateTime? dateStamp;

        /// <summary>
        /// Specifies the date and time when an iCalendar object was created. Maps to 
        /// the dtstamp field.
        /// </summary>
        public DateTime? DateStamp
        {
            get { return this.dateStamp; }
            set
            {
                this.dateStamp = value;
                this.AddPropertyChanged("DateStamp");
            }
        }

        private int? duration;

        /// <summary>
        /// Specifies the duration, in seconds, of an appointment or meeting.  Maps to 
        /// the duration field.
        /// </summary>
        public int? Duration
        {
            get { return this.duration; }
            set
            {
                this.duration = value;
                this.AddPropertyChanged("Duration");
            }
        }

        private string exDate = string.Empty;

        /// <summary>
        /// Contains a list of dates that are exceptions to a recurring appointment. 
        /// Exceptions are instances of the appointment that are deleted.  Maps to the exdate field.
        /// </summary>
        public string ExDate
        {
            get { return this.exDate; }
            set
            {
                this.exDate = value;
                this.AddPropertyChanged("ExDate");
            }
        }

        private string exRule = string.Empty;

        /// <summary>
        /// Specifies an exception rule for a recurring appointment. An exception rule is a repeating 
        /// pattern of exceptions.  Maps to the exrule field.
        /// </summary>
        public string ExRule
        {
            get { return this.exRule; }
            set
            {
                this.exRule = value;
                this.AddPropertyChanged("ExRule");
            }
        }

        private double? geoLatitude;

        /// <summary>
        /// Specifies the geographical latitude of the location of an appointment. Positive values 
        /// from 0 to 90 specify degrees north latitude. Negative values from 0 to -90 specify 
        /// degrees south latitude.  Maps to the geolatitude field.
        /// </summary>
        public double? GeoLatitude
        {
            get { return this.geoLatitude; }
            set
            {
                this.geoLatitude = value;
                this.AddPropertyChanged("GeoLatitude");
            }
        }

        private double? geoLongitude;

        /// <summary>
        /// Specifies the geographical longitude of the location of an appointment. Positive values 
        /// from 0 to 180 are degrees east longitude. Negative values from 0 to -180 are degrees 
        /// west longitude.  Maps to the geolongitude field.
        /// </summary>
        public double? GeoLongitude
        {
            get { return this.geoLongitude; }
            set
            {
                this.geoLongitude = value;
                this.AddPropertyChanged("GeoLongitude");
            }
        }

        private bool? hasAttachment;

        /// <summary>
        /// Read-only. Indicates whether or not the appointment has attachments.  Maps to 
        /// the hasattachment field.
        /// </summary>
        public bool? HasAttachment
        {
            get { return this.hasAttachment; }
            internal set
            {
                this.hasAttachment = value;
                this.AddPropertyChanged("HasAttachment");
            }
        }

        private string htmlDescription = string.Empty;

        /// <summary>
        /// The HTML content of the appointment.  Maps to the htmldescription field.
        /// </summary>
        public string HtmlDescription
        {
            get { return this.htmlDescription; }
            set
            {
                this.htmlDescription = value;
                this.AddPropertyChanged("HtmlDescription");
            }
        }

        private DateTime? lastModified;

        /// <summary>
        /// Specifies the date and time when an appointment was last modified. Maps to 
        /// the lastmodified field.
        /// </summary>
        public DateTime? LastModified
        {
            get { return this.lastModified; }
            set
            {
                this.lastModified = value;
                this.AddPropertyChanged("LastModified");
            }
        }

        private string location = string.Empty;

        /// <summary>
        /// Specifies the location of an appointment or meeting.  Maps to the location field.
        /// </summary>
        public string Location
        {
            get { return this.location; }
            set
            {
                this.location = value;
                this.AddPropertyChanged("Location");
            }
        }

        private string locationUrl = string.Empty;

        /// <summary>
        /// Specifies a URL where you can access location information in HTML format.  Maps to 
        /// the locationurl field.
        /// </summary>
        public string LocationUrl
        {
            get { return this.locationUrl; }
            set
            {
                this.locationUrl = value;
                this.AddPropertyChanged("LocationUrl");
            }
        }

        private Method? method;

        /// <summary>
        /// Specifies the iCalendar method that is associated with an appointment object.  Maps to 
        /// the method field.
        /// </summary>
        public Method? Method
        {
            get { return this.method; }
            set
            {
                this.method = value;
                this.AddPropertyChanged("Method");
            }
        }

        private string mileage = string.Empty;

        /// <summary>
        /// Used for Microsoft Outlook interoperability.  Maps to the mileage field.
        /// </summary>
        public string Mileage
        {
            get { return this.mileage; }
            set
            {
                this.mileage = value;
                this.AddPropertyChanged("Mileage");
            }
        }

        private string normalizedSubject = string.Empty;

        /// <summary>
        /// Subject text string with all prefixes such as "Re:" and "Fwd:" removed. 
        /// Maps to the normalizedsubject field.
        /// </summary>
        public string NormalizedSubject
        {
            get { return this.normalizedSubject; }
            internal set
            {
                this.normalizedSubject = value;
                this.AddPropertyChanged("NormalizedSubject");
            }
        }

        private Priority? priority;

        /// <summary>
        /// Sets the priority of a message as configured using the Exchange System Manager. 
        /// Maps to the priority field.
        /// </summary>
        public Priority? Priority
        {
            get { return this.priority; }
            set
            {
                this.priority = value;
                this.AddPropertyChanged("Priority");
            }
        }

        private string rdate = string.Empty;

        /// <summary>
        /// Contains a comma-delimitted of instances of a recurring appointment. The 
        /// instances are stored as the dates and times of the appointment.  Maps to 
        /// the rdate field.
        /// </summary>
        public string Rdate
        {
            get { return this.rdate; }
            set
            {
                this.rdate = value;
                this.AddPropertyChanged("Rdate");
            }
        }

        private string recurrenceId = string.Empty;

        /// <summary>
        /// A recurrence identifier that identifies a specific instance of a 
        /// recurring appointment. It is used with the Sequence property to uniquely 
        /// identify the instance. The value of the recurrence identifier 
        /// is the starting date and time of the specific instance.  The 
        /// RecurrenceIdRange property can modify the meaning of the RecurrenceId 
        /// property to refer to multiple instances of a recurring appointment.
        /// Maps to the recurrenceid field.
        /// </summary>
        public string RecurrenceId
        {
            get { return this.recurrenceId; }
            set
            {
                this.recurrenceId = value;
                this.AddPropertyChanged("RecurrenceId");
            }
        }

        private RecurrenceIdRange? recurrenceIdrange;

        /// <summary>
        /// Specifies which instances of a recurring appointment the RecurrenceId 
        /// property refers to. The value ThisAndFuture refers to the instance 
        /// specified by the RecurrenceId property and to all later instances of 
        /// the recurring appointment. The value ThisAndPrior refers to the instance 
        /// specified by the RecurrenceId property and to all earlier instances of 
        /// the recurring appointment. The default value is None, which means that 
        /// the RecurrenceId property refers to a single instance.  Maps to the 
        /// recurrenceidrange field.
        /// </summary>
        public RecurrenceIdRange? RecurrenceIdRange
        {
            get { return this.recurrenceIdrange; }
            set
            {
                this.recurrenceIdrange = value;
                this.AddPropertyChanged("RecurrenceIdRange");
            }
        }

        private DateTime? replyTime;

        /// <summary>
        /// Specifies the date and time when an attendee replied to a meeting request. 
        /// You can use this value to determine which response is the most recent when 
        /// an attendee sends more than one response to a meeting request.  Maps to the 
        /// replytime field.
        /// </summary>
        public DateTime? ReplyTime
        {
            get { return this.replyTime; }
            set
            {
                this.replyTime = value;
                this.AddPropertyChanged("ReplyTime");
            }
        }

        private string resources = string.Empty;

        /// <summary>
        /// Contains a list of resources, such as rooms and video equipment, that 
        /// are available for an appointment. The resources are specified by 
        /// mailto URIs, and are separated by commas.  Maps to the resources field.
        /// </summary>
        public string Resources
        {
            get { return this.resources; }
            set
            {
                this.resources = value;
                this.AddPropertyChanged("Resources");
            }
        }

        private string rrule = string.Empty;

        /// <summary>
        /// Contains the rule for the pattern that defines a recurring appointment. 
        /// The StartDate property specifies the first instance of the appointment. 
        /// The rule is based on the date and time of the first instance.  Maps to 
        /// the rrule field.
        /// </summary>
        public string Rrule
        {
            get { return this.rrule; }
            set
            {
                this.rrule = value;
                this.AddPropertyChanged("Rrule");
            }
        }

        private Sensitivity? sensitivity;

        /// <summary>
        /// Appointment sensitivity.  Maps to the sensitivity field.
        /// </summary>
        public Sensitivity? Sensitivity
        {
            get { return this.sensitivity; }
            set
            {
                this.sensitivity = value;
                this.AddPropertyChanged("Sensitivity");
            }
        }

        private int? sequence;

        /// <summary>
        /// Specifies the sequence number of a version of an appointment.  Maps to the sequence field.
        /// </summary>
        public int? Sequence
        {
            get { return this.sequence; }
            internal set
            {
                this.sequence = value;
                this.AddPropertyChanged("Sequence");
            }
        }

        private string subject = string.Empty;

        /// <summary>
        /// The subject of the appointment.  Maps to the subject field.
        /// </summary>
        public string Subject
        {
            get { return this.subject; }
            set
            {
                this.subject = value;
                this.AddPropertyChanged("Subject");
            }
        }

        private string textDescription = string.Empty;

        /// <summary>
        /// The plain text content of the appointment.  Maps to the textsescription field.
        /// </summary>
        public string TextDescription
        {
            get { return this.textDescription; }
            set
            {
                this.textDescription = value;
                this.AddPropertyChanged("TextDescription");
            }
        }

        private string timeZone = string.Empty;

        /// <summary>
        /// Specifies the time zone of an appointment or meeting. This property enables you 
        /// to define time zones that are not defined by <see cref="MIS.EN.Exchange.Entities.TimeZoneId"/>. 
        /// If you specify this property, the TimeZoneId property is ignored.  For appointments 
        /// that are received as iCalendar messages, this value is taken from the VTIMEZONE calendar 
        /// component of the appointment.  Maps to the timezone field.
        /// </summary>
        public string TimeZone
        {
            get { return this.timeZone; }
            set
            {
                this.timeZone = value;
                this.AddPropertyChanged("TimeZone");
            }
        }

        private Transparent? transparent;

        /// <summary>
        /// Specifies whether an appointment or meeting is visible to busy time searches. Maps to 
        /// the transparent field.
        /// </summary>
        public Transparent? Transparent
        {
            get { return this.transparent; }
            set
            {
                this.transparent = value;
                this.AddPropertyChanged("Transparent");
            }
        }

        private string uid = string.Empty;

        /// <summary>
        /// Specifies the unique identifier of an appointment or meeting.  Maps to the uid field.
        /// </summary>
        public string Uid
        {
            get { return this.uid; }
            set
            {
                this.uid = value;
                this.AddPropertyChanged("Uid");
            }
        }

        #endregion
    }
}
